<script lang="ts" setup>
    import {Picture, EditPen, Upload, Link} from "@element-plus/icons-vue";
    import {UploadRequestOptions} from "element-plus";

    // 当前菜单类型
    type MenuType = "brush" | "electoral" | "eraser";

    // 当前菜单数据接口
    interface MenuData
    {
        type: MenuType;
        name: string;
        icon: Component;
    }

    // 参数
    const props = defineProps({
        // 当前缩放值
        scale: {
            type: [Number, String],
            default: "auto"
        },
        // 当前激活的菜单
        active: {
            type: String,
            default: ""
        },
        // 画笔大小
        brush: {
            type: Number,
            default: 32
        },
        // 橡皮擦大小
        eraser: {
            type: Number,
            default: 32
        },
        // 画板宽度
        width: {
            type: Number,
            default: 0
        },
        // 画板高度
        height: {
            type: Number,
            default: 0
        },
        // 是否存在图片资源
        hasAssets: {
            type: Boolean,
            default: false
        }
    });

    // 数据集
    const dataBean = reactive<{
        scaleValue: number | string; // 当前缩放值
        activeMenu: MenuType | string; // 当前激活的菜单
        widthValue: number; // 画板宽度
        heightValue: number; // 画板高度
        assets: boolean; // 是否存在图片资源
    }>({
        scaleValue: "",
        activeMenu: "",
        widthValue: 0,
        heightValue: 0,
        assets: false
    });

    // 事件
    const emit = defineEmits<{
        (e: "click", type: string): void;
        (e: "changeScale", value: number | string): void;
        (e: "changeSize", argumentsList: {width: number; height: number}): void;
        (e: "upload", data: Record<string, any>): void;
        (e: "changeBrushSize", value: number): void;
        (e: "changeEraserSize", value: number): void;
        (e: "beforeUpload", value: UploadRequestOptions): void;
        (e: "uploadSuccess", value: UploadRequestOptions): void;
        (e: "uploadFail", error: Record<string, any>): void;
    }>();

    // 监听图片资源
    watchEffect(() =>
    {
        dataBean.assets = props.hasAssets;
    });

    // 菜单列表
    const menuList: MenuData[] = [
        {
            type: "brush",
            name: "画笔",
            icon: markRaw(EditPen)
        },
        {
            type: "electoral",
            name: "快速选择",
            icon: markRaw(Picture)
        },
        {
            type: "eraser",
            name: "橡皮擦",
            icon: markRaw(Picture)
        }
    ];

    // 当前缩放选项
    const scaleOptions: Record<string, any>[] = [
        {
            label: "全览",
            value: "auto"
        },
        {
            label: "50%",
            value: 0.5
        },
        {
            label: "75%",
            value: 0.75
        },
        {
            label: "100%",
            value: 1
        },
        {
            label: "200%",
            value: 2
        }
    ];

    // 监听
    watchEffect(() =>
    {
        // 设置面板宽度
        dataBean.widthValue = props.width || 0;

        // 设置画板高度
        dataBean.heightValue = props.height || 0;

        // 初始化当前激活的菜单
        dataBean.activeMenu = props.active || "";

        // 设置当前缩放
        dataBean.scaleValue = isNumber(props.scale) ? `${Math.round(props.scale * 100)}%` : props.scale;
    });

    // 组件挂载
    onMounted(() =>
    {
        // 初始化当前激活的菜单
        updateActiveMenu(props.active);
    });

    // 设置当前激活的菜单
    const updateActiveMenu = (type: string, fn?: () => void) =>
    {
        if (dataBean.activeMenu !== type)
        {
            dataBean.activeMenu = type;

            if (fn)
            {
                fn.apply(undefined);
            }
        }
    };

    // 点击事件
    const clickHandler = (data: MenuData) =>
    {
        if (!dataBean.assets)
        {
            return;
        }

        // 更新当前激活的菜单
        updateActiveMenu(data.type, () =>
        {
            emit("click", data.type);
        });
    };

    // 改变画笔大小事件
    const changeBrushHandler = (value: number | number[]): void =>
    {
        emit("changeBrushSize", isNumber(value) ? value : value[0]);
    };

    // 改变橡皮擦大小事件
    const changeEraserHandler = (value: number | number[]): void =>
    {
        emit("changeEraserSize", isNumber(value) ? value : value[0]);
    };

    // 改变缩放事件
    const changeScaleHandler = (value: string | number): void =>
    {
        // 执行事件
        emit("changeScale", value);
    };

    // 改变尺寸事件
    const changeSizeHandler = (argumentsList: Record<string, any>): void =>
    {
        const {event, type} = argumentsList || {};

        const target = event.target as HTMLInputElement;

        if (!target)
        {
            return;
        }

        // 当前的值
        const value = Number(target.value);

        if (value < 512 || value > 2048)
        {
            ElMessage.error("尺寸范围在512-2048之间");

            return;
        }

        // 更新面板宽度
        if (type === "width" && value !== props.width)
        {
            dataBean.widthValue = value;
        }

        // 更新画板高度
        if (type === "height" && value !== props.height)
        {
            dataBean.heightValue = value;
        }

        emit("changeSize", {width: dataBean.widthValue, height: dataBean.heightValue});
    };

    // 上传文件事件
    const uploadHandler = (data: UploadRequestOptions): XMLHttpRequest | Promise<void> =>
    {
        emit("beforeUpload", data);

        return new Promise<void>((resolve, reject) =>
        {
            uploadImage({img: data.file}).then((res: Record<string, any>) =>
            {
                const {code, data: {aiInfo = []}, message} = res || {};

                if (code === 200)
                {
                    if (aiInfo && isArray(aiInfo) && !isEmpty(aiInfo))
                    {
                        emit("uploadSuccess", aiInfo[0]);

                        resolve();
                    }
                    else
                    {
                        ElMessage.error("上传失败");

                        reject();
                    }
                }
                else if (message)
                {
                    ElMessage.error(message);

                    reject();
                }
            }).catch((error: Record<string, any>) =>
            {
                const {data: {message = ""}} = error || {};

                // 错误提示
                ElMessage.error(message);

                // 上传失败
                emit("uploadFail", error);

                reject();
            });
        });
    };
</script>

<template>
    <!-- 智能画布工具栏 -->
    <div class="smart-canvas-tools">
        <!-- 左侧 -->
        <div class="left">
            <!-- 上传按钮 -->
            <div class="upload">
                <div class="button">
                    <el-tooltip
                        content="上传图片"
                        placement="top"
                    >
                        <el-upload
                            :http-request="uploadHandler"
                            :show-file-list="false"
                            accept=".png, .jpg, .jpeg"
                            action="#"
                        >
                            <el-icon class="icon">
                                <Upload></Upload>
                            </el-icon>
                        </el-upload>
                    </el-tooltip>
                </div>
            </div>
            <!-- //上传按钮 -->

            <!-- 按钮 -->
            <div class="sub-container">
                <!-- 按钮 -->
                <div
                    v-for="item in menuList"
                    :key="item.type"
                    :class="['button', {active: dataBean.activeMenu === item.type}, {disabled: !dataBean.assets}]"
                    @click="clickHandler(item)"
                >
                    <el-tooltip
                        :content="dataBean.assets ? item.name : '请上传图片后使用'"
                        placement="top"
                    >
                        <el-icon class="icon">
                            <component :is="item.icon" />
                        </el-icon>
                    </el-tooltip>
                </div>
                <!-- //按钮 -->

                <!-- 分隔符 -->
                <div class="divider"></div>
                <!-- //分隔符 -->

                <!-- 按钮功能 -->
                <div class="button-operation">
                    <!-- 画笔 -->
                    <div
                        v-if="dataBean.activeMenu === 'brush'"
                        class="brush"
                    >
                        <!-- 滑块 -->
                        <div class="slider">
                            <el-slider
                                :model-value="brush"
                                :max="80"
                                :min="6"
                                size="small"
                                @input="changeBrushHandler"
                            ></el-slider>
                        </div>
                        <!-- //滑块 -->
                    </div>
                    <!-- //画笔 -->

                    <!-- 快速选区 -->
                    <div
                        v-if="dataBean.activeMenu === 'electoral'"
                        class="electoral"
                    >
                        请在图层上选择区域
                    </div>
                    <!-- //快速选区 -->

                    <!-- 橡皮擦 -->
                    <div
                        v-if="dataBean.activeMenu === 'eraser'"
                        class="eraser"
                    >
                        <!-- 滑块 -->
                        <div class="slider">
                            <el-slider
                                :model-value="eraser"
                                :max="80"
                                :min="6"
                                size="small"
                                @input="changeEraserHandler"
                            ></el-slider>
                        </div>
                        <!-- //滑块 -->
                    </div>
                    <!-- //橡皮擦 -->

                    <!-- 其他 -->
                    <div
                        v-if="!dataBean.activeMenu"
                        class="tips"
                    >
                        选择局部重绘操作
                    </div>
                    <!-- //其他 -->
                </div>
                <!-- //按钮功能 -->
            </div>
            <!-- //按钮 -->

            <!-- 当前画板尺寸 -->
            <div class="size">
                <el-popover
                    :width="240"
                    placement="bottom"
                    trigger="click"
                >
                    <template #reference>
                        <div class="inner">
                            <span>{{ dataBean.widthValue }}</span>
                            <span class="cover">×</span>
                            <span>{{ dataBean.heightValue }}</span>
                        </div>
                    </template>

                    <template #default>
                        <div class="tool-size-panel">
                            <!-- 标题 -->
                            <div class="title">画板调节</div>
                            <!-- //标题 -->

                            <!-- 内容 -->
                            <div class="content">
                                <!-- 块 -->
                                <div class="line">
                                    <!-- 块标题 -->
                                    <div class="line-title">画板尺寸</div>
                                    <!-- //块标题 -->

                                    <!-- 块内容 -->
                                    <div class="line-area">
                                        <!-- 宽度输入框 -->
                                        <div class="input">
                                            <el-input
                                                v-model.number="dataBean.widthValue"
                                                placeholder="宽度"
                                                type="text"
                                                @keydown.enter="(event: Event) => changeSizeHandler({event, type: 'width'})"
                                            >
                                                <template #prepend>
                                                    <span>W</span>
                                                </template>
                                            </el-input>
                                        </div>
                                        <!-- //宽度输入框 -->

                                        <!-- 图标 -->
                                        <div class="icon">
                                            <el-icon class="icon">
                                                <Link></Link>
                                            </el-icon>
                                        </div>
                                        <!-- //图标 -->

                                        <!-- 高度调节 -->
                                        <div class="input">
                                            <el-input
                                                v-model.number="dataBean.heightValue"
                                                placeholder="高度"
                                                type="text"
                                                @keydown.enter="(event: Event) => changeSizeHandler({event, type: 'height'})"
                                            >
                                                <template #prepend>
                                                    <span>H</span>
                                                </template>
                                            </el-input>
                                        </div>
                                        <!-- //高度调节 -->

                                        <!-- 单位 -->
                                        <div class="unit">px</div>
                                        <!-- //单位 -->
                                    </div>
                                    <!-- //块内容 -->
                                </div>
                                <!-- //块 -->
                            </div>
                            <!-- //内容 -->
                        </div>
                    </template>
                </el-popover>
            </div>
            <!-- //当前画板尺寸 -->
        </div>
        <!-- //左侧 -->

        <!-- 右侧 -->
        <div class="right">
            <!-- 下拉框 -->
            <div class="select">
                <el-select
                    v-model="dataBean.scaleValue"
                    placeholder="请选择"
                    placement="bottom"
                    @change="changeScaleHandler"
                >
                    <el-option
                        v-for="item in scaleOptions"
                        :key="item.value"
                        :label="item.label"
                        :value="item.value"
                    ></el-option>
                </el-select>
            </div>
            <!-- //下拉框 -->
        </div>
        <!-- //右侧 -->
    </div>
    <!-- //智能画布工具栏 -->
</template>

<style lang="scss" scoped>
    @use "sass:math";

    // 智能画布工具栏
    .smart-canvas-tools
    {
        display: flex;
        align-items: center;
        justify-content: space-between;

        // 左侧
        .left
        {
            display: flex;
            align-items: center;

            // 上传按钮
            .upload
            {
                .button
                {
                    display: flex;
                    align-items: center;
                    justify-content: center;
                    width: 36px;
                    height: 36px;
                    cursor: pointer;
                    border-radius: 8px;
                    background-color: #f5f5f5;

                    // 图标
                    .icon
                    {
                        font-size: 18px;
                        transition: color 0.3s linear;
                        color: #8b8b8b;
                    }

                    &:hover
                    {
                        background-color: #333;

                        // 图标
                        .icon
                        {
                            color: #fff;
                        }
                    }

                    ::v-deep(.el-upload)
                    {
                        width: 36px;
                        height: 36px;
                    }
                }
            }

            // 次级按钮
            .sub-container
            {
                display: flex;
                align-items: center;
                justify-content: center;
                margin-left: 5px;
                border-radius: 8px;
                background-color: #f5f5f5;

                // 按钮
                .button
                {
                    display: flex;
                    align-items: center;
                    justify-content: center;
                    width: 36px;
                    height: 36px;
                    cursor: pointer;
                    transition: background-color 0.3s linear,
                    color 0.3s linear;
                    border-radius: 8px;

                    // 图标
                    .icon
                    {
                        font-size: 18px;
                        transition: color 0.3s linear;
                        color: #8b8b8b;
                    }

                    // 激活
                    &:not(.disabled)
                    {
                        // 激活&悬停
                        &.active,
                        &:hover
                        {
                            background-color: #333;

                            // 图标
                            .icon
                            {
                                color: #fff;
                            }
                        }
                    }

                    &.disabled
                    {
                        cursor: no-drop;
                        opacity: 0.3;
                    }

                    &:not(:first-child)
                    {
                        margin-left: 5px;
                    }
                }

                // 分隔符
                .divider
                {
                    width: 1px;
                    height: 18px;
                    margin: 0 8px;
                    background-color: #e9e9e9;
                }

                // 按钮功能
                .button-operation
                {
                    display: flex;
                    align-items: center;
                    justify-content: center;
                    width: 232px;
                    margin-right: 8px;

                    // 刷子&橡皮擦
                    .brush,
                    .eraser
                    {
                        flex: 1;
                        padding: 0 16px;
                    }

                    // 快速选择
                    .electoral
                    {
                        font-size: 14px;
                        cursor: default;
                        text-align: center;
                        color: #afafaf;
                    }

                    // 提示
                    .tips
                    {
                        font-size: 14px;
                        cursor: default;
                        text-align: center;
                        color: #afafaf;
                    }
                }
            }

            // 当前画板尺寸
            .size
            {
                // 标题内盒
                .inner
                {
                    font-size: 14px;
                    display: flex;
                    align-items: center;
                    height: 36px;
                    margin-left: 10px;
                    padding: 0 8px;
                    cursor: pointer;
                    border-radius: 8px;

                    &:hover
                    {
                        color: #fff;
                        background-color: #333;
                    }
                }
            }
        }

        // 右侧
        .right
        {
            // 下拉框
            .select
            {
                width: 90px;
            }
        }
    }

    // 面板调节
    .tool-size-panel
    {
        // 标题
        .title
        {
            padding: 8px 0;
            border-bottom: 1px solid #e9e9e9;
        }

        // 内容
        .content
        {
            margin-top: 8px;

            // 块
            .line
            {
                // 标题
                .line-title
                {
                    font-size: 12px;
                }

                // 内容
                .line-area
                {
                    display: flex;
                    align-items: center;
                    margin-top: 6px;

                    // 输入框
                    .input
                    {
                        ::v-deep(.el-input)
                        {
                            .el-input-group__prepend
                            {
                                padding: 0 8px;

                                span
                                {
                                    font-size: 12px;
                                }
                            }
                        }
                    }

                    // 图标
                    .icon
                    {
                        width: 32px;
                        height: 32px;
                    }

                    // 单位
                    .unit
                    {
                        font-size: 12px;
                        margin-left: 4px;
                    }
                }
            }
        }
    }

    // 重写slider样式
    ::v-deep(.el-slider)
    {
        .el-slider__runway
        {
            $sliderHeight: 4px; // 轨道高度
            $sliderButtonSize: 16px; // 滑块大小
            $sliderOutsideSize: 36px; // 滑动轨大小
            $sliderStopSize: 10px; // 断点块大小

            height: $sliderHeight;
            border-radius: 4px;
            background-color: #c7c7c7;

            .el-slider__bar
            {
                height: $sliderHeight;
                border-radius: 4px 0 0 4px;
            }

            .el-slider__button-wrapper
            {
                top: -(math.div($sliderOutsideSize - $sliderHeight, 2));
                width: $sliderOutsideSize;
                // top: -($sliderOutsideSize - $sliderHeight) / 2;
                height: $sliderOutsideSize;

                .el-slider__button
                {
                    width: $sliderButtonSize;
                    height: $sliderButtonSize;
                    border-width: 1px;
                }
            }

            .el-slider__stop
            {
                top: -(math.div($sliderStopSize - $sliderHeight, 2));
                width: $sliderStopSize;
                // top: -($sliderStopSize - $sliderHeight) / 2;
                height: $sliderStopSize;
            }
        }
    }
</style>